package com.easy.frame.gateway;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author zzf
 * @date 11:23 2021/5/25
 */
@Slf4j
//@Configuration
public class DynamicRouteConfiguration {


    @Value("${spring.application.name}")
    private String routeDataId;

    @Value("${spring.cloud.nacos.config.group}")
    private String group;

    @Value("${spring.cloud.nacos.config.server-addr}")
    private String serverAddr;


    private final String whiteListId = "ef_white_list";

    private RouteDefinitionWriter writer;
    private ApplicationEventPublisher publisher;

    public DynamicRouteConfiguration(RouteDefinitionWriter writer, ApplicationEventPublisher publisher) {
        this.writer = writer;
        this.publisher = publisher;
    }

    @PostConstruct
    private void init() {
        Assert.notNull(routeDataId, "ksaas.dynamic.route.dataId null异常");
        Assert.notNull(group, "ksaas.dynamic.route.group is null异常");
        Assert.notNull(serverAddr, "ksaas.dynamic.route.ipAddr is null异常");
        dynamicRouteByNacosListener();
        dynamicWhiteListByNacosListener();
    }

    private void dynamicRouteByNacosListener() {
        try {
            ConfigService configService = NacosFactory.createConfigService(serverAddr);
            String content = configService.getConfigAndSignListener(
                    routeDataId,
                    group,
                    5000,
                    new AbstractListener() {
                        @Override
                        public void receiveConfigInfo(String configInfo) {
                            updateConfig(configInfo);
                        }
                    });
            updateConfig(content);
        } catch (NacosException e) {
            log.error("nacos 获取动态路由配置和监听异常", e);
        }
    }

    private void updateConfig(String content) {
        log.info("nacos 动态路由更新： {}", content);
        try {
            List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(content, RouteDefinition.class);
            gatewayRouteDefinitions.forEach(routeDefinition -> {

                log.info("动态路由配置: {}", routeDefinition);
                writer.delete(Mono.just(routeDefinition.getId()));
                writer.save(Mono.just(routeDefinition)).subscribe();
                publisher.publishEvent(new RefreshRoutesEvent(this));

            });
        } catch (Exception e) {
            log.error("更新动态路由配置异常: ", e);
        }
    }


    private void dynamicWhiteListByNacosListener() {
        try {
            ConfigService configService = NacosFactory.createConfigService(serverAddr);
            String content = configService.getConfigAndSignListener(
                    whiteListId,
                    group,
                    5000,
                    new AbstractListener() {
                        @Override
                        public void receiveConfigInfo(String configInfo) {

                            AuthenticationFilter.whiteList = JSONObject.parseArray(configInfo, String.class);
                        }
                    });
            AuthenticationFilter.whiteList = JSONObject.parseArray(content, String.class);
        } catch (NacosException e) {
            log.error("nacos 获取动态路由配置和监听异常", e);
        }
    }


}
